#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <stdio.h>
#include <string.h>

#include <map>
#include <vector>
#include <algorithm>


using namespace std;


int split(vector<string>& v, const string& str, char c)
{
v.clear();
string::const_iterator s = str.begin();
while (true) {
  string::const_iterator begin = s;

  while (*s != c && s != str.end()) { ++s; }

  v.push_back(string(begin, s));
  if (s == str.end()) {
    break;
  }
  if (++s == str.end()) {
    v.push_back("");
    break;
  }
}

}


std::string convert( double x )
{
   std::ostringstream oss;
   oss << x;
   return oss.str();
}
	 



int main(int argc, char *argv[ ]){

ifstream archivo;
ofstream salida;

ofstream salida_tipos_normal("salida_tipos.default-normal",ios::out);
ofstream salida_tipos_anormal("salida_tipos.default-anormal",ios::out);

int f,l,i,s,p;
s=0;
if(argc < 2){
  cout << "\nError: No se tiene el numero indicado de argumentos" << endl;
  cout << "Ayuda: ./parser -h \n" << endl;
  return -1;
}


for(i = 0; i < argc; i++){

 if(!strcmp(argv[i],"-h")){
    cout << endl<< endl;
    cout << "---=== AYUDA ===---" << endl << endl;
    cout << "Este programa hace un parseo de los archivo en formato kdd99 y luego los separa en dos (datos normales y datos anormales)" << endl;
    cout << "Modo de ejecucion" << endl;
    cout << "./parser -f <archivo de entrada> (-p <numero_de_columnas>)\n" << endl;
    cout << "La salida es en formato csv en los archivo salida.default-normal y salida.default-anormal" << endl;
    cout << "Los tipos quedan en el archivo salida_tipos.default-normal y salida_tipos.default-anormal" << endl;
    cout << endl << endl;
    return -1;
 }



 if(!strcmp(argv[i],"-f")){
   f=i+1;
   fprintf(stderr,"got to line %d\n",__LINE__);
   archivo.open(argv[f]);
   if(!archivo){
     cout << "Fallo al intentar abrir el archivo: " << argv[f] << endl;
     return -1;
   }
    fprintf(stderr,"got to line %d\n",__LINE__);
 }

 if(!strcmp(argv[i],"-l")){
   f=i+1;
   fprintf(stderr,"got to line %d\n",__LINE__);

   l=atoi(argv[f]);

   fprintf(stderr,"got to line %d\n",__LINE__);
 }else{

   l=-1;

 }
 if(!strcmp(argv[i],"-p")){
   f=i+1;
   fprintf(stderr,"got to line %d\n",__LINE__);

   p=atoi(argv[f]);

   fprintf(stderr,"got to line %d\n",__LINE__);
 }else{

   p=42;

 }


}



fprintf( stderr, "got to line %d\n", __LINE__ );


int j=0;
vector<string> v(p);
string linea;



map<int, vector<string> > matriz;
map<string,int> tipos_matriz;

map<int, vector<double> > matriz2;

fprintf( stderr, "got to line %d\n", __LINE__ );
while(! archivo.eof())
{
  getline (archivo,linea);
  split(v, linea, ',');


  matriz[j]=v;


  j++;

}
int h=0;
ifstream tipos_default("tipos_default.dat");

while(! tipos_default.eof())
{
  getline (tipos_default,linea);
  split(v, linea, ',');


  tipos_matriz[v[1].c_str()]=atoi(v[0].c_str());


  h++;

}

fprintf( stderr, "got to line %d\n", __LINE__ );




map<int, map<string,double> > tipos;



if(l==-1){

  //revisar
  l=matriz.size()-1;

  cout << "tamano de la matriz: " << l << endl;

}else{

  cout << "tamano de la matriz: " << l << endl;

}


int c=matriz[0].size();

cout << "-l == "<< l  << " c== " << c << endl;


   fprintf(stderr,"got to line %d\n",__LINE__);
for(i=0;i<l-1;i++){

  for(j=0;j<c;j++){
      if(tipos[j][matriz[i][j]]!=1.0 && strcmp(matriz[i][j].c_str(),"0") && strcmp(matriz[i][j].c_str(),"0.0") && strcmp(matriz[i][j].c_str(),"0.00") && atof(matriz[i][j].c_str())==0.0){

            tipos[j][matriz[i][j]]=1.0;

      }

//      cout << "i: " << i << " j: " << j << endl;
  }
  
}

   fprintf(stderr,"got to line %d\n",__LINE__);
//revisar si va
ofstream tipos_num("tipos.txt",ios::out);
ofstream ataque("ataque.txt",ios::out);

ofstream salida_datos("salida.datos",ios::out);
ofstream salida_tipos("salida.tipos",ios::out);



ofstream sali_a("salida.default-anormal",ios::out);

ofstream sali_n("salida.default-normal",ios::out);

map<string, double>::const_iterator itera;
int count=0;
int t= tipos.size();
int m;
cout << t << endl;

   fprintf(stderr,"got to line %d\n",__LINE__);
for(j=0;j<t;j++){
  m=0;

  for (itera=tipos[j].begin(); itera != tipos[j].end(); ++itera) {
    if(tipos[j][itera->first]!=0.0){
      tipos[j][itera->first]=m;
      tipos_num << j << "," << m << "," << itera->first << endl;
      m++;
    }
  }
 cout << endl;
}

//sali << "que onda loco!" << endl;

   fprintf(stderr,"got to line %d\n",__LINE__);

   fprintf(stderr,"got to line %d\n",__LINE__);

for(i=0;i<l-1;i++){
  matriz[i][1]=convert(tipos[1][matriz[i][1]]);
  matriz[i][2]=convert(tipos[2][matriz[i][2]]);
  matriz[i][3]=convert(tipos[3][matriz[i][3]]);

  ataque << i << "," << tipos[p-1][matriz[i][p-1]] << "," << matriz[i][p-1] << endl;

  matriz[i][p-1]=convert(tipos_matriz[matriz[i][p-1]]);


//cout << matriz[i][41] << endl;
if(strcmp(matriz[i][p-1].c_str(),"0")==0){

//cout << "matriz: " << matriz[i][41] << " " << strcmp(matriz[i][41].c_str(),"0") << " " << count << endl;
//cout << "tipos:" << tipos_matriz[matriz[i][41]] << endl;

count++;
salida_tipos_normal << matriz[i][p-1] << endl;
salida_tipos << matriz[i][p-1] << endl;



  for(j=0;j<c-1;j++){

//    cout << "-->" << matriz[i][j] << endl;
//cout << j << " " << c+1 << endl;
    if(j!=c-2){
      sali_n << matriz[i][j] << ",";
      salida_datos << matriz[i][j] << ",";
//      cout << matriz[i][j] << " ";
    }
    else{

      sali_n << matriz[i][j];
      salida_datos << matriz[i][j];
//      cout << matriz[i][j];
    }
  }

  sali_n << endl;
  salida_datos << endl;
//  cout << endl;

}else{
//cout << "matriz: " << matriz[i][41] << " " << strcmp(matriz[i][41].c_str(),"0") << " " << count << endl;
//cout << "tipos:" << tipos_matriz[matriz[i][41]] << endl;

count++;
salida_tipos_anormal << matriz[i][p-1] << endl;
salida_tipos << matriz[i][p-1] << endl;



  for(j=0;j<c-1;j++){

//    cout << "-->" << matriz[i][j] << endl;
//cout << j << " " << c+1 << endl;
    if(j!=c-2){
      sali_a << matriz[i][j] << ",";
      salida_datos << matriz[i][j] << ",";
//      cout << matriz[i][j] << " ";
    }
    else{

      sali_a << matriz[i][j];
      salida_datos << matriz[i][j];
//      cout << matriz[i][j];
    }
  }

  sali_a << endl;
  salida_datos << endl;
//  cout << endl;





}






}
   fprintf(stderr,"got to line %d\n",__LINE__);

   return 1;



}







